package com.heima.admin.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.heima.admin.mapper.AdChannelMapper;
import com.heima.admin.mapper.AdSensitiveMapper;
import com.heima.admin.service.WemediaNewsAutoScanService;
import com.heima.aliyun.GreenImageScan;
import com.heima.aliyun.GreenTextScan;
import com.heima.common.exception.CustException;
import com.heima.feigns.article.ArticleFeign;
import com.heima.feigns.wemedia.WemediaFeign;
import com.heima.model.admin.pojos.AdChannel;
import com.heima.model.article.dto.ArticleDto;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.media.pojos.WmNews;
import com.heima.model.media.pojos.WmUser;
import com.heima.utils.common.SensitiveWordUtil;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class WemediaNewsAutoScanServiceImpl implements WemediaNewsAutoScanService {

    @Autowired
    WemediaFeign wemediaFeign;
    @Autowired
    AdSensitiveMapper adSensitiveMapper;
    @Autowired
    GreenTextScan greenTextScan;
    @Autowired
    GreenImageScan greenImageScan;
    @Autowired
    AdChannelMapper adChannelMapper;
    @Autowired
    ArticleFeign articleFeign;
    @Value("${file.oss.web-site}")
    String webSite;

    /**
     * 根据文章id自动审核
     *
     * @param wmNewsId
     */
    @Override
    @Transactional
    @GlobalTransactional
    public void autoScanByMediaNewsId(Integer wmNewsId) {
        //参数验证
        if (wmNewsId == null) {
            log.error("自动审核文章，对应文章id为空");
            CustException.cust(AppHttpCodeEnum.PARAM_REQUIRE);
            return;
        }
        //远程调用wmnews的方法查询文章状态
        WmNews wmNews = wemediaFeign.findById(wmNewsId);
        //判断文章是否存在
        if (wmNews == null) {
            log.error("自动审核文章，对应文章id==>{} 不存在", wmNewsId);
            CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST, "文章数据不存在");
            return;
        }
        //根据文章id判断文章状态
        Short status = wmNews.getStatus();
        //文章状态为待审核
        if (status.equals(WmNews.Status.SUBMIT.getCode())) {
            auditArticle(wmNews);
        }
        //重新获取文章状态
        status = wmNews.getStatus();
        if (status.equals(WmNews.Status.ADMIN_SUCCESS.getCode()) || status.equals(WmNews.Status.SUCCESS.getCode())) {
            //判断发布时间是否小于当前时间
            if (wmNews.getPublishTime().before(new Date())) {
                //发布文章
                publishArticle(wmNews);
            }
        }
    }

    /**
     * 审核文章方法
     * @param wmNews
     */
    private void auditArticle(WmNews wmNews) {
        //提取文章中内容和图片
        Map<String, Object> map = handleTextAndImages(wmNews);
        //先审核敏感词
        Boolean flag = auditSensitiveWord(map.get("text").toString(), wmNews);
        if (flag == false) {
//            CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST, "敏感词审核失败");
            return;
        }
        //阿里云文本审核
        Boolean handleTextScanResult = handleTextScan(map.get("text").toString(), wmNews);
        if (flag == false) {
//            CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST, "阿里云文本审核失败");
            return;
        }
        //阿里云图片审核
        Boolean handleImagesScanResult = handleImagesScan((List) map.get("images"), wmNews);
        if(handleImagesScanResult==false){
//            CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST, "阿里云图片审核失败");
            return;
        }
        //修改文章状态
        updateWmNews(wmNews,(short)8,"审核通过");
    }

    /**
     * 阿里云图片审核
     * @param images
     * @param wmNews
     * @return
     */
    private Boolean handleImagesScan(List images, WmNews wmNews) {
        Boolean flag = true;
        try {
            Map map = greenImageScan.imageUrlScan(images);
            String suggestion = (String) map.get("suggestion");
            if (suggestion.equals("block")) {
                flag = false;
                updateWmNews(wmNews, (short) 2, "文章中存在违规图片");
            }
            if (suggestion.equals("review")) {
                flag = false;
                updateWmNews(wmNews, (short) 3, "文章中的图片需要人工审核");
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("阿里云图片审核异常,需要转入到人工审核异常为==>{}", e);
            flag = false;
            updateWmNews(wmNews, (short) 3, "文章中的图片需要人工审核");
        }
        return flag;
    }

    /**
     * 阿里云文本审核
     *
     * @param text
     * @param wmNews
     * @return
     */
    private Boolean handleTextScan(String text, WmNews wmNews) {
        Boolean flag = true;
        try {
            Map map = greenTextScan.greenTextScan(text);
            String suggestion = (String) map.get("suggestion");
            if (suggestion.equals("block")) {
                flag = false;
                updateWmNews(wmNews, (short) 2, "文本内容中含有敏感词");
            }
            if (suggestion.equals("review")) {
                flag = false;
                updateWmNews(wmNews, (short) 3, "文本中内容需要人工审核");
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("阿里云文本审核异常,需要转入到人工审核异常为==>{}", e);
            flag = false;
            updateWmNews(wmNews, (short) 3, "文本中内容需要人工审核");
        }
        return flag;
    }

    /**
     * 审核敏感词
     *
     * @param text
     * @return
     */
    private Boolean auditSensitiveWord(String text, WmNews wmNews) {
        Boolean flag = true;
        List<String> allSensitive = adSensitiveMapper.findAllSensitive();
        if (allSensitive == null) {
            log.error("自动审核文章，查询敏感词数据不存在");
            CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST, "查询敏感词数据不存在");
        }
        //判断文章中是否存在敏感词
        SensitiveWordUtil.initMap(allSensitive);
        Map<String, Integer> resultMap = SensitiveWordUtil.matchWords(text);
        if (resultMap.size() > 0) {
            log.info("自动审核文章，文本中存在敏感词为==> {}", resultMap);
            //更新文章状态
            updateWmNews(wmNews, (short) 2, "文章文本中存在敏感词：" + resultMap);
            flag = false;
        }
        return flag;
    }

    /**
     * 更新文章状态
     *
     * @param wmNews
     * @param status
     * @param resultMap
     */
    private void updateWmNews(WmNews wmNews, short status, String resultMap) {
        wmNews.setReason(resultMap);
        wmNews.setStatus(status);
        ResponseResult responseResult = wemediaFeign.updateWmNews(wmNews);
        if (!responseResult.getCode().equals(0)) {
            log.error("文章内容状态更新失败,文章id为==>{}", wmNews.getId());
            CustException.cust(AppHttpCodeEnum.SERVER_ERROR, "文章内容状态更新失败");
        }
    }

    /**
     * 提取文章文本和图片方法
     *
     * @param wmNews
     */
    private Map<String, Object> handleTextAndImages(WmNews wmNews) {
        List<Map> list = JSONArray.parseArray(wmNews.getContent(), Map.class);
        //拼接文本内容
        String text = list.stream()
                .filter(map -> map.get("type").equals("text"))
                .map(map -> map.get("value").toString())
                .collect(Collectors.joining("_hmtt_"));
        //添加标题内容一起参与阿里云检查
        text = wmNews.getTitle() + "_hmtt_" + text;
        //获取文章中图片集合
        List<String> collect = list.stream()
                .filter(map -> map.get("type").equals("image"))
                .map(map -> map.get("value").toString())
                .distinct()
                .collect(Collectors.toList());
        //判断封面是否有图片
        if (wmNews.getType() == null || wmNews.getType() == 1 || wmNews.getType() == 3) {
            List<String> coverImagesList = Arrays.asList(wmNews.getImages().split(","));
            coverImagesList.stream().map(image -> webSite + image)
                    .distinct()
                    .forEach(image -> collect.add(image));
        }
        HashMap<String, Object> map = new HashMap<>();
        map.put("text", text);
        map.put("images", collect);
        return map;
    }

    /**
     * 发布文章方法
     * @param wmNews
     */
    private void publishArticle(WmNews wmNews) {
        //保存文章
        ResponseResult result = saveArticle(wmNews);
        Long articleId = (long)result.getData();
        wmNews.setArticleId(articleId);
        updateWmNews(wmNews,(short)9,"审核通过");
    }

    /**
     * 远程调用article接口保存文章
     * @param wmNews
     */
    private ResponseResult saveArticle(WmNews wmNews) {
        //封装参数
        ArticleDto articleDto = new ArticleDto();
        BeanUtils.copyProperties(wmNews,articleDto);
        articleDto.setLayout(wmNews.getType());
        articleDto.setFlag((byte) 0);

        //判断文章中作品id是否为空，如果有则执行修改方法
        if(wmNews.getArticleId()!=null){
            articleDto.setId(wmNews.getArticleId());
        }else {
            //id字段设置null，由雪花算法控制
            articleDto.setId(null);
        }
        //根据频道id获取频道名称
        if(wmNews.getChannelId()!=null){
            articleDto.setChannelId(wmNews.getChannelId());
            AdChannel adChannel = adChannelMapper.selectById(wmNews.getChannelId());
            if(adChannel!=null){
                articleDto.setChannelName(adChannel.getName());
            }
        }
        //远程调用获取文章作者名称
        WmUser wmUser = wemediaFeign.findWmUserById(wmNews.getUserId());
        if(wmNews==null&&wmNews.getStatus()!=9){
            CustException.cust(AppHttpCodeEnum.AD_USER_STUTAS_INVLID);
        }
        articleDto.setAuthorName(wmUser.getName());
        return articleFeign.saveArticle(articleDto);
    }
}
